<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style type="text/css">
        button {
            margin:20px;
        }
    </style>
</head>
<body onload="showRole();">
    <div id="canvasDiv" style="width:100%; height:652px; display:flex; justify-content:center;">
        <canvas id="myCanvas" width="1000" height="650" style="border: black 1px solid; margin-top:2px;">
            你的浏览器不支持canvas，请更换其他浏览器试一试。
        </canvas>
        <img src="img/icon03.png" id="genguin" style="display: none;">        
        <img src="img/fj.png" id="plane" style="display: none;">        
        <img src="img/gsp.png" id="gun" style="display: none;">        
        <img src="img/bomb.png" id="bomb" style="display: none;">   
    </div>
    <div id="buttonDiv" style="width:100%; display:flex; justify-content:center;">
       <button onclick="playGame();">开始</button><button onclick="goLeft();">左移</button>
       <button onclick="goRight();">右移</button><button onclick="fire();">开炮</button>
    </div>
    <script type="text/javascript">
        var canvas = document.getElementById("myCanvas");
        var context = canvas.getContext("2d");
        var image = document.getElementById("plane");
        var image2 = document.getElementById("gun");
        var image3 = document.getElementById("genguin");
        var image5 = document.getElementById("bomb");
        var explode01 =  new Image();
        explode01.src = "img/explode01.png";
        var explode02 =  new Image();
        explode02.src = "img/explode02.png";
        var explode03 =  new Image();
        explode03.src = "img/explode03.png";
        var explode04 =  new Image();
        explode04.src = "img/explode04.png";
        var imageMissile = new Image();
        imageMissile.src = "img/dd8.png";
        var level = 1;
        var score = 0;
        var planeSpeed = 5;
        var planeSpeed2 = 12;
        var planeStartPointX = 2;
        var planeStartDownthrustPointX = 2;
        var planeStartPointY = 69;
        var planeStartTowards = 0;
        var planeWidth = 169;
        var planeHeight = 138;
        var nowPlaneTowards = planeStartTowards;
        var nowPlanePosX = planeStartPointX;
        var nowPlanePosY = planeStartPointY;
        var nowPlaneSpeedY = 0;
        var nowPlaneHitted = false;
        var nowPlaneFlyMode = "horizontal";
        var planeHittedPosY = planeStartPointY;
        var planeHittedTowards;
        var nowPlaneTimeAfterHitted = 0;
        var deltAngle = 0;
        var gunStartTowards = 0;
        var nowGenguinTowards = gunStartTowards;
        var gunMoveSpeed = 10;
        var gunPosX = 1000/2-30;
        var gunPosY = 650-90;
        var gunHitted = false;
        var gunTimeAfterHitted = 0;
        var gunFireGap = 5;
        var genguinFireSpeed = 15;
        var genguinPosX = gunPosX+11;
        var genguinPosY = gunPosY-16
        var fired = false;
        var gameLoop;
        var shell = [];
        var missile = [];
        var missileStart = false;
        var missileTimeAfterFired = 0;
        var missilePosX, missilePosY, missileWidth=114, missileHeight=18, missileSpeedX, missileSpeedY, missileTowards, missileAcceleration;
        var distanceX2Gun, time2ReachGun, rotateSpeed, accelerationX, gunPriorPosX;
        var missileFirePosX, missileFirePosY;
        for (var j=0; j<10; j++) {
            shell[j] = [];
            shell[j][0] = false; //shell[j][0] shell visible;
        }
        for (var j=0; j<3; j++) {
            missile[j] = [];
            missile[j][0] = false; //missile[j][0] missile visible;
        }
        var bombArray = [];
        for (var j=0; j<5; j++) {
            bombArray[j] = [];
            bombArray[j][0] = false; //bombArray[j][0] bombArray visible;
        }
        function showRole() {
            context.drawImage(image, nowPlanePosX-planeWidth/2, nowPlanePosY-planeHeight/2);
            context.drawImage(image3, genguinPosX, genguinPosY);            
            context.drawImage(image2, gunPosX, gunPosY);
            if (typeof(localStorage.level) != "undefined") 
            {
                level = parseInt(localStorage.level);
//                localStorage.level = 3;
            } else {
                level = 1;
            }
			showLevelAndScore();

			document.onkeydown=function(event){
				var e = event || window.event || arguments.callee.caller.arguments[0];
				e.stopPropagation();  //阻止事件的冒泡传播
				e.preventDefault();  //阻止按键单击导致默认事件的发生
				if (e.keyCode==40) {
					playGame();
				}	
				if(e.keyCode==37){
					goLeft();         //left
				}
				if(e.keyCode==39){   //right
					goRight();
				}
				if(e.keyCode==32){    //spacebar
					fire();
				}
			} 
			
        }
        function showLevelAndScore() {
            context.font = '12pt 宋体';
            context.fillText("第" + level +"关", 10, 600);
            context.fillText("得分：" + score, 10, 620);
        }
        function showFailure() {
            context.font = '12pt 宋体';
            context.fillText("第" + level +"关", 10, 600);
            context.fillText("失败！", 10, 620);
        }
        function showSuccess() {
            context.font = '12pt 宋体';
            context.fillText("第" + level +"关", 10, 600);
            context.fillText("成功过关！", 10, 620);
        }
        function showFinish() {
            context.font = '12pt 宋体';
            context.fillText("你已经通过了最后一关！", 10, 600);
            context.fillText("游戏结束！", 10, 620);
        }
        function playGame() {
			if (gameLoop != null) {
				clearInterval(gameLoop);
			}
            planeStartPointX = -3;
            nowPlanePosX = planeStartPointX;
            nowPlanePosY = planeStartPointY;
            nowPlaneHitted = false;
            nowPlaneTimeAfterHitted = 0;
            nowPlaneFlyMode = "horizontal";
            gunPosX = 1000/2-30;
            gunHitted = false;
            gunTimeAfterHitted = 0;
            gunStartTowards = -Math.PI/2;
            genguinPosX = gunPosX+11;
            nowGenguinTowards = gunStartTowards;
            score = 0;
            for (var i=0; i<10; i++) {
                    shell[i][0] = false;
                }
            for (var i=0; i<3; i++) {
                    missile[i][0] = false;
                }
            gameLoop = setInterval(function(){gamePerformance();},50);
        }
        function goLeft() {
            context.clearRect(gunPosX, gunPosY-16, 57, 106);
            gunPosX -= gunMoveSpeed;
            genguinPosX = gunPosX+11;
            genguinPosY = gunPosY-16;
            context.drawImage(image3, genguinPosX, genguinPosY);            
            context.drawImage(image2, gunPosX, gunPosY);
            return;
        }
        function goRight() {
            context.clearRect(gunPosX, gunPosY-16, 57, 106);
            gunPosX += gunMoveSpeed;
            genguinPosX = gunPosX+11;
            genguinPosY = gunPosY-16;
            context.drawImage(image3, genguinPosX, genguinPosY);            
            context.drawImage(image2, gunPosX, gunPosY);
            return;
        }
        function fire() {
            if (!gunHitted && gunFireGap<0) {
                for(var k=0; k<10; k++) {
                    if (!shell[k][0]) {
                        shell[k][0] = true; //shell[j][0] shell visible;
                        shell[k][1] = gunPosX+11; //shell[k][1] shell position X
                        shell[k][2] = gunPosY-16; //shell[k][2] shell position Y
                        shell[k][3] = gunStartTowards; ///shell[k][2] shell direction
                        gunFireGap = 5;
                        break;
                    }
                }
            }
        }
        function gamePerformance() {
            gunFireGap--;
            context.clearRect(0,0,1000,650);
            if ((level<3) && (Math.random() > (0.96/(Math.sqrt(level)))) && !nowPlaneHitted) {  //condition for throw bomb
                for (var i=0; i<5; i++) {
                    if (!bombArray[i][0]) {
                        if (level == 1) {
                            bombArray[i][0] = true; //visible
                            bombArray[i][1] = nowPlanePosX+80; //bomb[i][1] position X
                            bombArray[i][2] = nowPlanePosY+120; //bomb[i][2] position Y
                            bombArray[i][3] = 0; //count after throw
                            bombArray[i][4] = bombArray[i][2];  //bomb[i][4] original position Y
                            break;
                        } else {
                            if ((Math.sqrt(Math.pow(nowPlanePosX-gunPosX, 2) + Math.pow(nowPlanePosY-gunPosY, 2)) < 350) && !gunHitted) {
                                bombArray[i][0] = true; //visible
                                bombArray[i][1] = nowPlanePosX; //bomb[i][1] position X
                                bombArray[i][2] = nowPlanePosY+80; //bomb[i][2] position Y
                                bombArray[i][3] = 0; //count after throw
                                bombArray[i][4] = bombArray[i][2];  //bomb[i][4] original position Y
                                break;
                            }
                        }
                    }
                }
            } else {
                if ((level==3) && (Math.random() > (0.96)) && !missileStart && !nowPlaneHitted) {
                    for (var i=0; i<3; i++) {
                        if (!missile[i][0]) {
                            missile[i][0] = true; 
                            missile[i][1] = nowPlanePosX;  //missileFirePosX
                            missile[i][2] = nowPlanePosY + 50;  //missileFirePosY
                            missile[i][3] = missile[i][1];  //missilePosX
                            missile[i][4] = missile[i][2];  //missilePosY
                            missile[i][5] = planeSpeed2;  //missileSpeedX
                            missile[i][6] = 0; //missileSpeedY
                            missile[i][7] = 0;  //missileTowards
                            missile[i][8] = 0;  //missileTimeAfterFired
                            missile[i][9] = gunPosX+28 - missile[i][3];  //distance2Gun
                            missile[i][10] = Math.sqrt((gunPosY-missile[i][4])/0.3); //time2ReachGun
                            if (gunPosX<(missile[i][1]+missile[i][10]*planeSpeed2)) {
                                missile[i][11] = (Math.PI - missile[i][7])/missile[i][10];  //rotateSpeed
                            } else {
                                missile[i][11] = (Math.PI/2 - missile[i][7])/missile[i][10];  //rotateSpeed
                            }
                            missile[i][12] = (missile[i][9]-missile[i][5]*missile[i][10])*2/Math.pow(missile[i][10],2);  //accelerationX
                            missile[i][13] = gunPosX; //gunPriorPosX;
                            break;
                        }
                    }
                }
            }
            for (var j=0; j<5; j++) {
                if (bombArray[j][0]) {
                    bombArray[j][1] = bombArray[j][1] + (level==1 ? planeSpeed : planeSpeed2);
                    bombArray[j][2] = bombArray[j][4] + (level==1 ? 0.3 : 0.3)*bombArray[j][3]*bombArray[j][3];
                    bombArray[j][3] += 1;
                    if (bombArray[j][2] > 640 || bombArray[j][1] > 950) {
                        bombArray[j][0] = false;
                    }
                    context.drawImage(image5, bombArray[j][1], bombArray[j][2]);
                }
            }
            if ((level==2) && ((gunPosX - nowPlanePosX)<400) && (gunPosX>nowPlanePosX) && (!nowPlaneHitted) && (nowPlaneFlyMode=="horizontal")) {
                nowPlaneFlyMode = "downthrust";
                planeStartDownthrustPointX = nowPlanePosX;
            } 
//if ((level==1) || ((nowPlanePosX>480) && (nowPlaneTowards>=Math.PI*2)))
            if ((level!=2) || (nowPlaneFlyMode == "horizontal")) {
                if (level==1) {
                    nowPlanePosX += planeSpeed;
                } else {
                    nowPlanePosX += planeSpeed2;
                }
            } else {
                nowPlanePosX += planeSpeed2;
            }
            if (nowPlaneHitted) {
                nowPlanePosY = planeHittedPosY + nowPlaneSpeedY*nowPlaneTimeAfterHitted + 0.3*nowPlaneTimeAfterHitted*nowPlaneTimeAfterHitted;
                drawDamagedPlane(level);
                nowPlaneTimeAfterHitted++;
            } else {
//if ((level==1) || (((nowPlanePosX>480) && (nowPlaneTowards>=Math.PI*2)))                
                if ((level!=2) ||  (nowPlaneFlyMode=="horizontal")) {
                    context.drawImage(image, nowPlanePosX-planeWidth/2, nowPlanePosY-planeHeight/2);
                } else {
                    nowPlaneTowards += Math.PI/20;
                    var previousPlanePosY = nowPlanePosY;
//                    nowPlanePosY = planeStartPointY + 200 - Math.sin(((nowPlanePosX-planeStartPointX)*Math.PI/240)+Math.PI/2)*200;
                    nowPlanePosY = planeStartPointY + 200 - Math.sin(((nowPlanePosX-planeStartDownthrustPointX)*Math.PI/240)+Math.PI/2)*200;
                    nowPlaneSpeedY = nowPlanePosY - previousPlanePosY;
//    				deltAngle = (Math.PI*3/2)+Math.atan(Math.cos(((nowPlanePosX-planeStartPointX)*Math.PI/240)+Math.PI/2));
                    deltAngle = (Math.PI*3/2)+Math.atan(Math.cos(((nowPlanePosX-planeStartDownthrustPointX)*Math.PI/240)+Math.PI/2));
//                    console.log("planePosX:", nowPlanePosX, "planePosY:", nowPlanePosY, "deltAngle:", deltAngle, "towards:", nowPlaneTowards);
                    context.translate(nowPlanePosX, nowPlanePosY);
                    context.rotate((Math.PI/2)-deltAngle+Math.PI);
                    context.drawImage(image, -planeWidth/2, -planeHeight/2);
                    context.rotate(deltAngle-(Math.PI/2)-Math.PI);
                    context.translate(-nowPlanePosX, -nowPlanePosY);
                    if (nowPlaneTowards>=Math.PI*2) {
                        nowPlaneFlyMode = "horizontal";
						nowPlaneTowards = 0;
                    }
                }
            }
//deal with missile action--begin
            for (var j=0; j<3; j++) {
                if (missile[j][0]) {
                    context.translate(missile[j][3], missile[j][4]);
                    context.rotate(missile[j][7]);
                    context.drawImage(imageMissile, -missileWidth/2, -missileHeight/2);
                    context.rotate(-missile[j][7]);
                    context.translate(-missile[j][3], -missile[j][4]);
                    if ((Math.abs(gunPosY+41-missile[j][4])<30) && !gunHitted && missile[j][0]) {
//                        console.log("gunPosX+28:", gunPosX+28, "missilePosX:", missilePosX, "gunPosY+41:", gunPosY+41, "missilePosY:", missilePosY);
//                        console.log("missilePosX-30:", missilePosX-30);
                        if (Math.abs(gunPosX+28-missile[j][3]+30)<55) {
//                            console.log("Hitted!");
                            gunHitted = true;
                            gunTimeAfterHitted = 0;
                        }    
                    }
                    if (missile[j][13] != gunPosX) {
                        var deltaAcceleratioX = 2*(gunPosX-missile[j][13])/Math.pow((missile[j][10]-missile[j][8]),2);
                        if (deltaAcceleratioX>75) {
                            deltaAcceleratioX = 75;
                        } else {
                            if (deltaAcceleratioX<-75) {
                                deltaAcceleratioX = -75;
                            }
                        }
                        missile[j][3] = missile[j][1] + planeSpeed2*missile[j][8] + 0.5*missile[j][12]*Math.pow(missile[j][8],2) + 0.5*deltaAcceleratioX;
                    } else {
                        missile[j][3] = missile[j][1] + planeSpeed2*missile[j][8] + 0.5*missile[j][12]*Math.pow(missile[j][8],2);
                    }
                    missile[j][4] = missile[j][2] + 0.6*Math.pow(missile[j][8],2)/2;
                    missile[j][7] += missile[j][11];
                    missile[j][8]++;
                    missile[j][13] = gunPosX;
                }
            }
//deal with missile action--end            
            if ((nowPlanePosX > 1327) || (nowPlanePosY > 580)) {
                if (gunHitted) {
                    clearInterval(gameLoop);
                    score = 0;
                    showFailure();
//                    return;
                } 
                if (nowPlaneTimeAfterHitted && (score>=150)) {
                    clearInterval(gameLoop);
                    score = 0;
                    if (level==3) {
                        showFinish();
                    } else {
                        showSuccess();
                        level += 1;
                        localStorage.level = level;
                    }
//                    return;
                }
                nowPlaneHitted = false;
                nowPlaneTimeAfterHitted = 0;
                nowPlaneTowards = planeStartTowards;
                nowPlanePosX = planeStartPointX;
                nowPlanePosY = planeStartPointY;
                nowPlaneFlyMode = "horizontal";
                for (var i=0; i<10; i++) {
                    shell[i][0] = false;
                }
                for (var i=0; i<3; i++) {
                    missile[i][0] = false;
                }
                return;
            } else {
                for (var i=0; i<10; i++) {
                    if (shell[i][0] && shell[i][2]>-32) {
                        shell[i][2] -= genguinFireSpeed;
                        shell[i][3] += Math.PI/10; 
                        if (shell[i][2]<-32) {
                            shell[i][0] = false;
                        }
                        context.translate(shell[i][1]+16, shell[i][2]+16);
                        context.rotate(shell[i][3]);
                        context.drawImage(image3, -16, -16);   
                        context.rotate(-shell[i][3]);       
                        context.translate(-shell[i][1]-16, -shell[i][2]-16);
                        if (((shell[i][1]+16)>(nowPlanePosX-planeWidth/4)) && ((shell[i][1]+16)<(nowPlanePosX+planeWidth/4)) && ((shell[i][2]+16)>(nowPlanePosY-planeHeight/4)) && ((shell[i][2]+16)<(nowPlanePosY+planeHeight/4)) && !nowPlaneHitted) {
                            nowPlaneHitted = true;
                            nowPlaneTimeAfterHitted = 0;
                            planeHittedPosY = nowPlanePosY;
                            planeHittedTowards = nowPlaneTowards;
                            score += 50;
                        }
                    } 
                }
                for (var j=0; j<5; j++) {
                    if (bombArray[j][0]) {
                        if (Math.abs(gunPosX-bombArray[j][1]) < 20) {
//                            console.log("gunPosX:", gunPosX, "gunPosY:", gunPosY, "gunPosX+50:", gunPosX+50, "gunPosY+80:", gunPosY+80);
//                            console.log("bombArray[j][1]:", bombArray[j][1], "bombArray[j][2]:", bombArray[j][2], "bombArray[j][1]+50:", bombArray[j][1]+50, "bombArray[j][2]+20:", bombArray[j][2]+20);
                            if ((level==1 ? (gunPosY<bombArray[j][2]+25) : (Math.abs(gunPosY - bombArray[j][2])<50))) {
                                gunHitted = true;
                                gunTimeAfterHitted = 0;
                                break;
                            }    
                        }    
                    }
                }
                if (gunHitted) {
                    gunTimeAfterHitted++;
                    switch(gunTimeAfterHitted) {
                        case 1: 
                        case 2:
                        case 3:
                            context.drawImage(image3, genguinPosX, genguinPosY);            
                            context.drawImage(image2, gunPosX, gunPosY);
                            context.drawImage(explode01, gunPosX+28-24, gunPosY+41-24);
                            break;
                        case 4:
                        case 5:
                        case 6:
                        case 7:
                        case 8:
                            context.drawImage(image2, gunPosX, gunPosY);
                            context.drawImage(explode02, gunPosX+28-40, gunPosY+41-34);
                            break;
                        case 9:
                        case 10:
                        case 11:
                        case 12:
                        case 13:
                            context.drawImage(image2, gunPosX, gunPosY);
                            context.drawImage(explode03, gunPosX+28-60, gunPosY+41-48);
                            break;
                        case 14:
                        case 15:
                        case 16:
                        case 17:
                        case 18:
                            context.drawImage(explode04, gunPosX+28-85, gunPosY+41-72);
                            break;
                    }
                } else {
                    context.drawImage(image3, genguinPosX, genguinPosY);            
                    context.drawImage(image2, gunPosX, gunPosY);
                }
            }
            showLevelAndScore();
        }
        function drawDamagedPlane(vel) {
            var kz = Math.floor(nowPlaneTimeAfterHitted/2);
            var kz2 = Math.floor((nowPlaneTimeAfterHitted-12)/2);
            var kz3 = Math.floor((nowPlaneTimeAfterHitted-18)/2);
            var kz4 = Math.floor((nowPlaneTimeAfterHitted-26)/2);
            switch(nowPlaneTimeAfterHitted) {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                case 8:
                case 9:
                    drawHittedPlane(vel);
                    context.drawImage(explode01, nowPlanePosX-24-2*kz, nowPlanePosY-24-2*kz, 48+4*kz, 48+4*kz);
                    break;
                case 10:
                case 11:
                case 12:
                case 13:
                case 14:
                case 15:
                case 16:
                case 17:
                    drawHittedPlane(vel);
                    context.drawImage(explode02, nowPlanePosX-40-6*kz2, nowPlanePosY-34-5*kz2, 80+12*kz2, 68+10*kz2);
                    break;
                case 18:
                case 19:
                case 20:
                case 21:
                case 22:
                case 23:
                case 24:
                case 25:
                    drawHittedPlane(vel);
                    context.drawImage(explode03, nowPlanePosX-60-8*kz3, nowPlanePosY-48-8*kz3, 120+16*kz3, 96+16*kz3);
                    break;
                case 26:
                case 27:
                case 28:
                case 29:
                case 30:
                case 31:
                    context.drawImage(explode04, nowPlanePosX-85-9*kz4, nowPlanePosY-72-9*kz4, 170+18*kz4, 144+18*kz4);
                    break;
            }
        }
        function drawHittedPlane(task) {
            if (task!=2) {
                context.drawImage(image, nowPlanePosX-planeWidth/2, nowPlanePosY-planeHeight/2);
            } else {
                context.translate(nowPlanePosX, nowPlanePosY);
                context.rotate((Math.PI/2)-deltAngle+Math.PI);
                context.drawImage(image, -planeWidth/2, -planeHeight/2);
                context.rotate(deltAngle-(Math.PI/2)-Math.PI);
                context.translate(-nowPlanePosX, -nowPlanePosY);
            }
        }
    </script>
</body>
</html>